home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 14642 / 14642.xpi / chrome / content / settings.js < prev    next >
Text File  |  2009-10-15  |  26KB  |  581 lines

  1. /* Copyright 2008, Boomtango.com.  All Rights Reserved. */
  2. /* settings.js
  3.  * Responsible for updating settings fields
  4.  */
  5.  
  6.  
  7. Components.utils.import("resource://boomtango/app.js");
  8. Components.utils.import("resource://boomtango/storage.js");
  9.  
  10. var mgr = {
  11.     panes: {
  12.         // general tab
  13.         general : {
  14.             NUMPERPAGE : [ 10, 25, 50, 100 ],
  15.             ITEMSPERCAT : [ 5, 10, 25 ],
  16.             YEAR: 60 * 24 * 365,
  17.             TABDELAY : [ 0, 5, 15, 60, 60 * 24 * 365 ],
  18.             VIEWS : [ 'category', 'calendar', 'piechart', 'thumbnail'],
  19.             DURS : [ 'hour', 'day', 'week', 'month'],
  20.  
  21.             onLoad: function(){
  22.                 var menu = document.getElementById("numPerPage");
  23.                 var len = this.NUMPERPAGE.length;
  24.                 var curr = boomtangoApp.searchItemsPerPage;
  25.                 for(var x = 0; x < len; x++){
  26.                     var num = this.NUMPERPAGE[x];
  27.  
  28.                     menu.appendItem(num);
  29.                     if(num == curr){
  30.                         menu.selectedIndex = x;
  31.                     }
  32.                 }
  33.                 var menu = document.getElementById("itemsPerCat");
  34.                 var len = this.ITEMSPERCAT.length;
  35.                 var curr = boomtangoApp.glanceItemsPerPage;
  36.                 for(var x = 0; x < len; x++){
  37.                     var num = this.ITEMSPERCAT[x];
  38.  
  39.                     menu.appendItem(num);
  40.                     if(num == curr){
  41.                         menu.selectedIndex = x;
  42.                     }
  43.                 }
  44.  
  45.                 var menu = document.getElementById("defaultView");
  46.                 var len = this.VIEWS.length;
  47.                 var curr = boomtangoApp.historyView;
  48.                 for(var x = 0; x < len; x++){
  49.                     var id = this.VIEWS[x];
  50.  
  51.                     menu.appendItem(boomtangoApp.getString('view.'+id));
  52.                     if(id == curr){
  53.                         menu.selectedIndex = x;
  54.                     }
  55.                 }
  56.  
  57.                 var menu = document.getElementById("defaultDur");
  58.                 var len = this.VIEWS.length;
  59.                 var curr = boomtangoApp.historyDur;
  60.                 for(var x = 0; x < len; x++){
  61.                     var id = this.DURS[x];
  62.  
  63.                     menu.appendItem(boomtangoApp.getString('dur.'+id));
  64.                     if(id == curr){
  65.                         menu.selectedIndex = x;
  66.                     }
  67.                 }
  68.  
  69.                 var menu = document.getElementById("tabDelay");
  70.                 var len = this.TABDELAY.length;
  71.                 var curr = boomtangoApp.tabChangeTime;
  72.                 for(var x = 0; x < len; x++){
  73.                     var num = this.TABDELAY[x];
  74.                     var label = num.toString();
  75.                     if(num == this.YEAR){
  76.                        label = boomtangoApp.getString("settings.never"); 
  77.                     }
  78.  
  79.                     menu.appendItem(label);
  80.                     if(num == curr){
  81.                         menu.selectedIndex = x;
  82.                     }
  83.                 }
  84.  
  85.                 document.getElementById("btversion").
  86.                     setAttribute("value",
  87.                         boomtangoApp.getString("settings.version", 
  88.                             boomtangoApp.ext_version));
  89.                 document.getElementById("dbversion").
  90.                     setAttribute("value",
  91.                         boomtangoApp.getString("settings.dbversion", 
  92.                             boomtangoApp.dbversion));
  93.                 document.getElementById("uselog").checked = boomtangoApp.uselog;
  94.                 document.getElementById("usethumb").checked = boomtangoApp.usethumb;
  95.             },
  96.             onDefaultView: function(){
  97.                 var menu = document.getElementById("defaultView");
  98.                 boomtangoApp.historyView = this.VIEWS[menu.selectedIndex];
  99.             },
  100.             onDefaultDur: function(){
  101.                 var menu = document.getElementById("defaultDur");
  102.                 boomtangoApp.historyDur = this.DURS[menu.selectedIndex];
  103.             },
  104.             onItemsPerCatChange: function(){
  105.                 var menu = document.getElementById("itemsPerCat");
  106.                 boomtangoApp.glanceItemsPerPage = this.ITEMSPERCAT[menu.selectedIndex];
  107.             },
  108.             onPerPageChange: function(){
  109.                 var menu = document.getElementById("numPerPage");
  110.                 boomtangoApp.searchItemsPerPage = this.NUMPERPAGE[menu.selectedIndex];
  111.             },
  112.             onTabDelayChange: function(){
  113.                 var menu = document.getElementById("tabDelay");
  114.                 boomtangoApp.tabChangeTime = this.TABDELAY[menu.selectedIndex];
  115.             },
  116.             onThumbClick: function(){
  117.                 boomtangoApp.usethumb = !boomtangoApp.usethumb;
  118.             },
  119.             onLogClick: function(){
  120.                 boomtangoApp.uselog = !boomtangoApp.uselog;
  121.             },
  122.             onShowLog: function(){
  123.                 boomtangoApp.showLogFile();
  124.             },
  125.             onOK: function() { return true;},
  126.             onCancel: function() {}
  127.         },
  128.         // storage tab
  129.         storage : {
  130.             onLoad: function(){
  131.                 var el = document.getElementById("deleteHistoryButton");
  132.                 var self = this;
  133.                 el.addEventListener(
  134.                     "click",
  135.                     function(e){
  136.                         if(e.ctrlKey){
  137.                             e.preventDefault();
  138.                             self.onDeleteAll();
  139.                         } else {
  140.                             self.onDeleteHistory();
  141.                         }
  142.                     },
  143.                     true
  144.                 );
  145.             },
  146.             onOK: function() { return true;},
  147.             onCancel: function() {},
  148.             onDeleteThumbs: function() {
  149.                 var prompt = Components.
  150.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  151.                     .getService(Components.interfaces.nsIPromptService); 
  152.                             
  153.  
  154.                 var result = prompt.confirm(
  155.                     window, 
  156.                     boomtangoApp.getString("settings.thumbprompt.title"),
  157.                     boomtangoApp.getString("settings.thumbprompt.text")
  158.                 );
  159.                 
  160.                 if (result) {
  161.                     boomtangoStorage.deleteAllThumb();
  162.                     var prompt = Components.
  163.                         classes["@mozilla.org/embedcomp/prompt-service;1"] 
  164.                         .getService(Components.interfaces.nsIPromptService); 
  165.                     var observer = Components.classes["@mozilla.org/observer-service;1"].
  166.                         getService(Components.interfaces.nsIObserverService);
  167.                     observer.notifyObservers(null, "boomtango-refreshviews", "");
  168.                     prompt.alert(window, "Boomtango", boomtangoApp.getString("settings.success.thumbdelete"));
  169.                 }
  170.             },
  171.             onDeleteAll: function() {
  172.                 var prompt = Components.
  173.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  174.                     .getService(Components.interfaces.nsIPromptService); 
  175.                             
  176.  
  177.                 var result = prompt.confirm(
  178.                     window, 
  179.                     boomtangoApp.getString("settings.historyall.title"),
  180.                     boomtangoApp.getString("settings.historyall.text")
  181.                 );
  182.                 
  183.                 if (result) {
  184.                     boomtangoApp.killBTData = true;
  185.                     Components.classes["@mozilla.org/toolkit/app-startup;1"].
  186.                         getService(Components.interfaces.nsIAppStartup).
  187.                         quit(
  188.                                 Components.interfaces.nsIAppStartup.eAttemptQuit |
  189.                                 Components.interfaces.nsIAppStartup.eRestart 
  190.                             );
  191.                                 
  192.                 }
  193.             },
  194.             onDeleteHistory: function() {
  195.                 var prompt = Components.
  196.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  197.                     .getService(Components.interfaces.nsIPromptService); 
  198.                             
  199.  
  200.                 var result = prompt.confirm(
  201.                     window, 
  202.                     boomtangoApp.getString("settings.historyprompt.title"),
  203.                     boomtangoApp.getString("settings.historyprompt.text")
  204.                 );
  205.                 
  206.                 if (result) {
  207.                     boomtangoStorage.deleteAllTrackers();
  208.                     var observer = Components.classes["@mozilla.org/observer-service;1"].
  209.                         getService(Components.interfaces.nsIObserverService);
  210.                     observer.notifyObservers(null, "boomtango-refreshviews", "");
  211.                     var prompt = Components.
  212.                         classes["@mozilla.org/embedcomp/prompt-service;1"] 
  213.                         .getService(Components.interfaces.nsIPromptService); 
  214.                     prompt.alert(window, "Boomtango", boomtangoApp.getString("settings.success.historydelete"));
  215.                 }
  216.             },
  217.             onChooseBackup: function() {
  218.                 var fp = Components.classes["@mozilla.org/filepicker;1"]
  219.                             .createInstance(Components.interfaces.nsIFilePicker);
  220.                 fp.defaultString = "backup.btd";
  221.                 fp.init(window, "Boomtango", fp.modeSave);
  222.                 fp.appendFilter("Boomtango", "*.btd");
  223.  
  224.                 var rv = fp.show();
  225.                 if (rv == fp.returnOK || rv == fp.returnReplace) {
  226.                     var textbox = document.getElementById("backup_textbox");
  227.                     textbox.value = fp.file.path;
  228.                     var button = document.getElementById("backup_button");
  229.                     button.disabled = false;
  230.                 }
  231.             },
  232.             onBackupInput: function(input) {    
  233.                 boomtangoApp.log("onBackupInput: " + input.value);
  234.                 document.getElementById("backup_button").disabled = !input.value;
  235.             },  
  236.             onBackup: function() {
  237.                 var textbox = document.getElementById("backup_textbox");
  238.                 // TODO: Need to process errors
  239.                 var rv = boomtangoStorage.backupToFile(textbox.value);
  240.                 var prompt = Components.
  241.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  242.                     .getService(Components.interfaces.nsIPromptService); 
  243.                 prompt.alert(window, "Boomtango", boomtangoApp.getString(rv?"settings.success.backup":"settings.failure.backup"));
  244.             },
  245.             onChooseRestore: function(){
  246.                 var fp = Components.classes["@mozilla.org/filepicker;1"]
  247.                             .createInstance(Components.interfaces.nsIFilePicker);
  248.                 fp.init(window, "Boomtango", fp.modeOpen);
  249.                 fp.appendFilter("Boomtango", "*.btd");
  250.  
  251.                 var rv = fp.show();
  252.                 if (rv == fp.returnOK || rv == fp.returnReplace) {
  253.                     var textbox = document.getElementById("restore_textbox");
  254.                     textbox.value = fp.file.path;
  255.                     var button = document.getElementById("restore_button");
  256.                     button.disabled = false;
  257.                 }
  258.             },
  259.             onRestoreInput: function(input) {    
  260.                 document.getElementById("restore_button").disabled = !input.value;
  261.             },  
  262.             onRestore: function() {
  263.                 var textbox = document.getElementById("restore_textbox");
  264.                 // TODO: Need to process errors
  265.                 var rv = boomtangoStorage.restoreFromFile(textbox.value);
  266.  
  267.                 var prompt = Components.
  268.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  269.                     .getService(Components.interfaces.nsIPromptService); 
  270.                 prompt.alert(window, "Boomtango", 
  271.                                 boomtangoApp.getString(rv?"settings.success.restore":"settings.failure.restore"));
  272.                 var observer = Components.classes["@mozilla.org/observer-service;1"].
  273.                     getService(Components.interfaces..nsIObserverService);
  274.                 observer.notifyObservers(null, "boomtango-refreshviews", "");
  275.                
  276.             }
  277.         },
  278.         // blacklist tab
  279.         blacklist : {
  280.             onLoad: function(){
  281.                 var addresses = boomtangoApp.getBlacklist();
  282.                 var list = document.getElementById("blacklist_list");
  283.                 for(var x in addresses){
  284.                     if(addresses.hasOwnProperty(x) && x != "web"){
  285.                         list.appendItem(addresses[x], x);
  286.                     }
  287.                 }
  288.  
  289.                 list.selectedIndex = 0;
  290.                 document.getElementById("address_remove").disabled = !list.getRowCount();
  291.                 document.getElementById("address_remove_all").disabled = !list.getRowCount();
  292.             },
  293.             onAddressInput: function(input) {    
  294.                 document.getElementById("address_block").disabled = !input.value;
  295.             },  
  296.             onAddressKeyPress: function (aEvent)
  297.             {
  298.                 if (aEvent.keyCode == KeyEvent.DOM_VK_RETURN)
  299.                     document.getElementById("address_block").click();
  300.             },
  301.             onAddressBlock: function() {
  302.                 var textbox = document.getElementById("address");
  303.                 var host = textbox.value.replace(/^\s*([-\w]*:\/+)?/, ""); // trim any leading space and scheme
  304.                 
  305.                 var addresses = boomtangoApp.getBlacklist();
  306.                 
  307.                 for(var x in addresses){
  308.                     if(addresses[x] == host){
  309.                         return;
  310.                     }
  311.                 }
  312.  
  313.                 //var host = textbox.value;
  314.                 boomtangoApp.addBlacklistData(host, false);
  315.                 
  316.                 var list = document.getElementById("blacklist_list");
  317.                 list.appendItem(host, host);
  318.                 
  319.                 document.getElementById("address_remove").disabled = !list.getRowCount();
  320.                 document.getElementById("address_remove_all").disabled = !list.getRowCount();
  321.             },
  322.             onAddressRemove: function(){
  323.                 var prompt = Components.
  324.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  325.                     .getService(Components.interfaces.nsIPromptService); 
  326.                             
  327.                 var list = document.getElementById("blacklist_list");
  328.                 
  329.                 var addresses = boomtangoApp.getBlacklist();
  330.                 var item = list.getItemAtIndex(list.selectedIndex);
  331.                 var data = addresses[item.value];
  332.                 
  333.                 boomtangoApp.deleteBlacklistData(data);
  334.                 var oldIndex = list.selectedIndex;
  335.                 list.removeItemAt(list.selectedIndex);
  336.                 list.selectedIndex = (oldIndex < list.getRowCount())?oldIndex:(oldIndex - 1);
  337.                 document.getElementById("address_remove").disabled = !list.getRowCount();
  338.                 document.getElementById("address_remove_all").disabled = !list.getRowCount();
  339.             },
  340.             onAddressRemoveAll: function(){
  341.                 var prompt = Components.
  342.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  343.                     .getService(Components.interfaces.nsIPromptService); 
  344.  
  345.                 var list = document.getElementById("blacklist_list");
  346.                 var types = boomtangoApp.tracker.types;
  347.                 var item = list.getItemAtIndex(list.selectedIndex);
  348.                 var data = types[item.value];
  349.                 var result = prompt.confirm(
  350.                     window, 
  351.                     boomtangoApp.getString("settings.removealladdress.title"),
  352.                     boomtangoApp.getString("settings.removealladdress.text")
  353.                 );
  354.                 
  355.                 if (result) {
  356.                     boomtangoApp.deleteAllBlacklist();
  357.                     for (i = list.getRowCount() - 1;i >= 0; i--) {
  358.                         list.removeItemAt(i);
  359.                     }
  360.                 }
  361.                 document.getElementById("address_remove").disabled = !list.getRowCount();
  362.                 document.getElementById("address_remove_all").disabled = !list.getRowCount();
  363.             },
  364.             onOK: function() { return true;},
  365.             onCancel: function() {}
  366.         },
  367.         // tracking tab
  368.         tracking : {
  369.             onLoad: function(){
  370.                 var types = boomtangoApp.tracker.types;
  371.                 var list = document.getElementById("tracker");
  372.                 for(var x in types){
  373.                     if(types.hasOwnProperty(x) && x != "web"){
  374.                         list.appendItem(types[x].name, x);
  375.                     }
  376.                 }
  377.  
  378.                 list.selectedIndex = 0;
  379.             },
  380.             onListSelect: function(){
  381.                 var list = document.getElementById("tracker");
  382.                 var types = boomtangoApp.tracker.types;
  383.                 var item = list.getItemAtIndex(list.selectedIndex);
  384.                 if(!item){
  385.                     return;
  386.                 }
  387.                 var data = types[item.value];
  388.                 
  389.                 document.getElementById("tracker_current")
  390.                     .setAttribute("label", data.name);
  391.                 document.getElementById("tracker_enable").
  392.                     setAttribute("checked",
  393.                     boomtangoApp.getTrackerEnabled(item.value));
  394.                 document.getElementById("tracker_color").color = 
  395.                     boomtangoApp.getTrackerColor(item.value);
  396.  
  397.                 document.getElementById("tracker_resetcolor").
  398.                     setAttribute("hidden", 
  399.                         boomtangoApp.getTrackerColor(item.value) ==
  400.                             data.color);
  401.  
  402.                 var desc = document.getElementById("tracker_desc");
  403.                 while(desc.firstChild){
  404.                     desc.removeChild(desc.firstChild);
  405.                 }
  406.                 desc.appendChild(document.createTextNode(data.description));
  407.                 document.getElementById("tracker_delete").
  408.                     setAttribute("disabled", data.isInternal);
  409.  
  410.                 document.getElementById("tracker_advanced").
  411.                     setAttribute("hidden", !data.onAdvancedLoad);
  412.                 
  413.                 document.getElementById("tracker_version").
  414.                     setAttribute("hidden", !data.plugin_version);
  415.                 if(data.plugin_version){
  416.                     document.getElementById("plugin_version").
  417.                         setAttribute("value", data.plugin_version);
  418.                 }
  419.                 document.getElementById("plugin_url").
  420.                     setAttribute("hidden", !data.plugin_url);
  421.                 if(data.plugin_url){
  422.                     document.getElementById("plugin_url").
  423.                         setAttribute("href", data.plugin_url + "?id="+data.id.split('.').slice(1).join('.') + "&version="+data.plugin_version);
  424.                 }
  425.                 
  426.                 window.sizeToContent();
  427.             },
  428.             onAdvanced: function(){
  429.                 var list = document.getElementById("tracker");
  430.                 var types = boomtangoApp.tracker.types;
  431.                 var item = list.getItemAtIndex(list.selectedIndex);
  432.                 window.openDialog("chrome://boomtango/content/pluginAdvanced.xul", "",
  433.                     "chrome, dialog, modal", types[item.value]).focus();
  434.             },
  435.             onEnable: function(){
  436.                 var  enableit = !document.getElementById("tracker_enable").checked;
  437.                 var list = document.getElementById("tracker");
  438.                 var types = boomtangoApp.tracker.types;
  439.                 var item = list.getItemAtIndex(list.selectedIndex);
  440.                 boomtangoApp.tracker.enableTracker(item.value, enableit);
  441.             },
  442.             onColor: function(){
  443.                 var color = document.getElementById('tracker_color').color;
  444.                 var list = document.getElementById("tracker");
  445.                 var types = boomtangoApp.tracker.types;
  446.                 var item = list.getItemAtIndex(list.selectedIndex);
  447.                 boomtangoApp.setTrackerColor(item.value, color);
  448.  
  449.                 document.getElementById("tracker_resetcolor").
  450.                     setAttribute("hidden", 
  451.                         boomtangoApp.getTrackerColor(item.value) ==
  452.                             types[item.value].color);
  453.             },
  454.             onResetColor: function(){
  455.                 var list = document.getElementById("tracker");
  456.                 var types = boomtangoApp.tracker.types;
  457.                 var item = list.getItemAtIndex(list.selectedIndex);
  458.                 boomtangoApp.resetTrackerColor(item.value);
  459.                 document.getElementById('tracker_color').color = types[item.value].color;
  460.                 document.getElementById("tracker_resetcolor").
  461.                     setAttribute("hidden","true"); 
  462.             },
  463.             onCreate:function(){
  464.                 var retVal = { type: null };
  465.                 window.openDialog("chrome://boomtango/content/createCategory.xul", "",
  466.                     "chrome, dialog, modal", retVal).focus();
  467.                 if(retVal.type){
  468.                     var types = boomtangoApp.tracker.types;
  469.                     var list = document.getElementById("tracker");
  470.  
  471.                     list.selectItem(list.appendItem(types[retVal.type].name, retVal.type));
  472.                 }
  473.             },
  474.             onImport: function(){
  475.                 var prompt = Components.
  476.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  477.                     .getService(Components.interfaces.nsIPromptService); 
  478.                             
  479.  
  480.                 var list = document.getElementById("tracker");
  481.                 var types = boomtangoApp.tracker.types;
  482.                 var item = list.getItemAtIndex(list.selectedIndex);
  483.                 var data = types[item.value];
  484.                 var result = prompt.confirm(
  485.                     window, 
  486.                     boomtangoApp.getString("settings.importtracker.title"),
  487.                     boomtangoApp.getString("settings.importtracker.text")
  488.                 );
  489.                 
  490.                 if (result) {
  491.                     var fp = Components.classes["@mozilla.org/filepicker;1"]
  492.                                 .createInstance(Components.interfaces.nsIFilePicker);
  493.                     fp.init(window, "Boomtango", fp.modeOpen);
  494.                     fp.appendFilter("Boomtango", "*.bct");
  495.  
  496.                     var rv = fp.show();
  497.                     if (rv == fp.returnOK || rv == fp.returnReplace) {
  498.                         var type = boomtangoApp.tracker.importTracker(fp.file);
  499.                         if(type != '????'){
  500.                             var types = boomtangoApp.tracker.types;
  501.                             var list = document.getElementById("tracker");
  502.  
  503.                             list.selectItem(list.appendItem(types[type].name, type));
  504.                         }
  505.                     }
  506.                 }
  507.             },
  508.             onDelete: function(){
  509.                 var prompt = Components.
  510.                     classes["@mozilla.org/embedcomp/prompt-service;1"] 
  511.                     .getService(Components.interfaces.nsIPromptService); 
  512.                             
  513.  
  514.                 var list = document.getElementById("tracker");
  515.                 var types = boomtangoApp.tracker.types;
  516.                 var item = list.getItemAtIndex(list.selectedIndex);
  517.                 var data = types[item.value];
  518.                 var result = prompt.confirm(
  519.                     window, 
  520.                     boomtangoApp.getString("settings.deletetracker.title"),
  521.                     boomtangoApp.getString("settings.deletetracker.text", data.name)
  522.                 );
  523.                 
  524.                 if (result) {
  525.                     boomtangoApp.tracker.deleteTracker(item.value);
  526.                     var oldIndex = list.selectedIndex;
  527.                     list.removeItemAt(list.selectedIndex);
  528.                     list.selectedIndex = oldIndex - 1;
  529.                 }
  530.             },
  531.             onOK: function() { return true;},
  532.             onCancel: function() {}
  533.         },
  534.  
  535.     },
  536.  
  537.     onLoad: function(){
  538.         var panes = this.panes;
  539.         for(var x in panes){
  540.             if(panes.hasOwnProperty(x)){
  541.                 panes[x].onLoad();
  542.             }
  543.         }
  544.  
  545.         // prefwindow on mac doesn't resize properly
  546.         if (navigator.platform.toLowerCase().indexOf('mac') > -1){ 
  547.             window.addEventListener(
  548.                 "resize",
  549.                 function(){
  550.                     window.setTimeout(
  551.                         function(){
  552.                             window.sizeToContent();
  553.                         },
  554.                         0
  555.                     );
  556.                 },
  557.                 false
  558.             );
  559.         }
  560.     },
  561.     onCancel: function(){
  562.         var panes = this.panes;
  563.         for(var x in panes){
  564.             if(panes.hasOwnProperty(x)){
  565.                 panes[x].onCancel();
  566.             }
  567.         }
  568.     },
  569.     onOK: function(){
  570.         var panes = this.panes;
  571.         for(var x in panes){
  572.             if(panes.hasOwnProperty(x)){
  573.                 if(!panes[x].onOK()){
  574.                     return false;
  575.                 }
  576.             }
  577.         }
  578.         return true;
  579.     }
  580. };
  581.